package ULHT.LIG2N1.RC.SERVER;

import ULHT.LIG2N1.RC.VO.GameLimitVO;
import ULHT.LIG2N1.RC.VO.QuestionLimitVO;
import org.joda.time.DateTime;

/**
 * VO de dados do jogo do cliente
 *
 * @author Administrador
 */
public class ClientGameData {

    // fields
    private String ipAdress;
    private String token;
    private boolean blacklisted;
    private String UDPuniHost;
    private int UDPuniPort;
    private String UDPmultiHost;
    private int UDPmultiPort;
    private long lastAnswerTime;
    private int CorrectAnswersInLevel;
    private int lastQuestionAnswered;
    private long score;
    private long totalScore;
    private long totalTime;
    private boolean lastAnswerCorrect;
    // para o controlo da resposta individual
    private DateTime horaPergunta;
    private DateTime horaResposta;
    private DateTime horaInicio;
    private DateTime horaTermino;
    private int currentLevel;
    private int currentQuestion;
    private boolean disqualified;
    private int totalCorrectAnswers;
    private String state;
    private boolean gameStarted;

    public ClientGameData() {
        this.disqualified = false;
        this.lastAnswerCorrect = false;
        this.blacklisted = false;
        this.state = "IDLE";
        this.gameStarted = false;
    }

    public ClientGameData(String ipAdress, String token, String UDPuniHost, int UDPuniPort, String UDPmultiHost, int UDPmultiPort) {
        this.ipAdress = ipAdress;
        this.token = token;
        this.blacklisted = false;
        this.UDPuniHost = UDPuniHost;
        this.UDPuniPort = UDPuniPort;
        this.UDPmultiHost = UDPmultiHost;
        this.UDPmultiPort = UDPmultiPort;
        this.lastAnswerTime = 0;
        this.CorrectAnswersInLevel = 0;
        this.disqualified = false;
        this.lastQuestionAnswered = 0;
        this.currentLevel = 0;
        this.currentQuestion = 1;
        this.lastAnswerCorrect = false;
        this.totalTime = 0;
    }
    
    
    public void setTotalScore(long totalScore) {
        this.totalScore = totalScore;
    }

    public DateTime getHoraPergunta() {
        return horaPergunta;
    }

    public void setTotalTime(long totalTime) {
        this.totalTime = totalTime;
    }

    public long getTotalTime() {
        return totalTime;
    }

    public String getTotalTimeStr() {
        DateTime tempo = new DateTime(totalTime);
        return tempo.toString("s.SSSS");
    }

    /**
     * @return Incrementa o Score do jogador
     */
    public long addToScore(long score) {
        this.totalScore += score;
        return this.totalScore;
    }

    /**
     * @return the blacklisted
     */
    public boolean isBlacklisted() {
        return blacklisted;
    }

    /**
     * @param blacklisted the blacklisted to set
     */
    public void setBlacklisted(boolean blacklisted) {
        this.blacklisted = blacklisted;
    }

    /**
     *
     */
    public void makeBlacklisted() {
        this.blacklisted = true;
    }

    /**
     * @return the UDPuniHost
     */
    public String getUDPuniHost() {
        return UDPuniHost;
    }

    /**
     * @param UDPuniHost the UDPuniHost to set
     */
    public void setUDPuniHost(String UDPuniHost) {
        this.UDPuniHost = UDPuniHost;
    }

    /**
     * @return the UDPuniPort
     */
    public int getUDPuniPort() {
        return UDPuniPort;
    }

    /**
     * @param UDPuniPort the UDPuniPort to set
     */
    public void setUDPuniPort(int UDPuniPort) {
        this.UDPuniPort = UDPuniPort;
    }

    /**
     * @return the UDPmultiHost
     */
    public String getUDPmultiHost() {
        return UDPmultiHost;
    }

    /**
     * @param UDPmultiHost the UDPmultiHost to set
     */
    public void setUDPmultiHost(String UDPmultiHost) {
        this.UDPmultiHost = UDPmultiHost;
    }

    /**
     * @return the UDPmultiPort
     */
    public int getUDPmultiPort() {
        return UDPmultiPort;
    }

    /**
     * @param UDPmultiPort the UDPmultiPort to set
     */
    public void setUDPmultiPort(int UDPmultiPort) {
        this.UDPmultiPort = UDPmultiPort;
    }

    /**
     * @return the lastAnswerTime
     */
    public long getLastAnswerTime() {
        return lastAnswerTime;
    }

    public String gatLastAnswerTimeStr() {
        return Float.toString((float) lastAnswerTime / 1000);
    }

    /**
     * @param lastAnswerTime the lastAnswerTime to set
     */
    public void setLastAnswerTime(long lastAnswerTime) {
        this.lastAnswerTime = lastAnswerTime;
    }

    /**
     * @return the CorrectAnswersInLevel
     */
    public int getCorrectAnswersInLevel() {
        return CorrectAnswersInLevel;
    }

    /**
     * @param CorrectAnswersInLevel the CorrectAnswersInLevel to set
     */
    public void setCorrectAnswersInLevel(int CorrectAnswersInLevel) {
        this.CorrectAnswersInLevel = CorrectAnswersInLevel;
    }

    /**
     * @return the ipAdress
     */
    public String getIpAdress() {
        return ipAdress;
    }

    /**
     * @param ipAdress the ipAdress to set
     */
    public void setIpAdress(String ipAdress) {
        this.ipAdress = ipAdress;
    }

    /**
     * @return the lastQuestionAnswered
     */
    public int getLastQuestionAnswered() {
        return lastQuestionAnswered;
    }

    /**
     * @param lastQuestionAnswered the lastQuestionAnswered to set
     */
    public void setLastQuestionAnswered(int lastQuestionAnswered) {
        this.lastQuestionAnswered = lastQuestionAnswered;
    }

    /**
     * @return the score
     */
    public long getScore() {
        return totalScore;
    }

    /**
     * @param score the score to set
     */
    public void setScore(long score) {
        this.score = score;
    }

    /**
     * @return the token
     */
    public String getToken() {
        return token;
    }

    /**
     * @param token the token to set
     */
    public void setToken(String token) {
        this.token = token;
    }

    public void startAnswering(int questionNumber) {
        this.horaPergunta = DateTime.now();
        this.lastAnswerTime = 0;
        this.lastQuestionAnswered = questionNumber;
    }

    public void StopAnswering() {
        this.horaResposta = DateTime.now();
    }

    public void calculateAnswerTime(boolean isCorrect, int timeOut, long score) {
        this.lastAnswerTime = horaResposta.getMillis() - horaPergunta.getMillis();
        this.lastAnswerCorrect = isCorrect;
        if (isCorrect) {
            this.CorrectAnswersInLevel++;
            this.totalCorrectAnswers++;
            this.addToScore(score);
            this.setScore(score);
            this.totalTime += this.lastAnswerTime;
        } else {
            this.setScore(0);
        }
    }

    public void levelUp() {
        this.currentLevel++;
        this.CorrectAnswersInLevel = 0;
    }

    public boolean isLastAnswerCorrect() {
        return lastAnswerCorrect;
    }

    public int getCurrentLevel() {
        return currentLevel;
    }

    public void initGameTimers() {
        if (!gameStarted) {
            this.horaInicio = DateTime.now();
            this.horaTermino = horaInicio.plusMillis(GameLimitVO.gameSessionTimeMillis());
            gameStarted = true;
        }
    }

    public long getTimeTillSessionEnd() {
        return horaTermino.getMillis() - DateTime.now().getMillis();
    }

    public void nextQuestion() {
        this.currentQuestion++;
        this.currentLevel = QuestionLimitVO.getquestionLevel(currentQuestion);
    }

    public int getQuestionNumber() {
        return this.currentQuestion;
    }

    public boolean isDisqualified() {
        return disqualified;
    }

    public void setDisqualified(boolean disqualified) {
        this.disqualified = disqualified;
    }

    public void Disqualify() {
        this.disqualified = true;
    }

    public void setCurrentLevel(int currentLevel) {
        this.currentLevel = currentLevel;
    }

    public int getTotalCorrectAnswers() {
        return totalCorrectAnswers;
    }

    public void setTotalCorrectAnswers(int totalCorrectAnswers) {
        this.totalCorrectAnswers = totalCorrectAnswers;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void resetState() {
        this.state = "IDLE";
    }

    public void advanceState() {
        switch (state) {
            case "IDLE":
            case "INGAME":
                this.state = "SENTTIMEOUT";
                break;
            case "SENTTIMEOUT":
                this.state = "SENTQUESTION";
                break;
            case "SENTQUESTION":
                this.state = "SENTRESULT";
                break;
            case "SENTRESULT":
                this.state = "INGAME";
                break;
        }
    }
}
